<template>
  <div class="w-full">
    <div class="border border-br-light rounded pt-2 pl-2 pb-3 pr-2 box-border">
      <div class="mb-2 flex justify-between">
        <el-checkbox v-model="checkAll" :indeterminate="isIndeterminate" @change="setMenuCheck" style="font-size: 16px">
          主导航菜单
        </el-checkbox>
        <div class="select-none">
          <el-link type="primary" @click="setMenuOpenOrClose(true)">展开</el-link>
          <span class="text-sm align-middle ml-0.5 mr-0.5">/</span>
          <el-link type="info" @click="setMenuOpenOrClose(false)">折叠</el-link>
        </div>
      </div>
      <el-tree
        class="pl-2"
        ref="treeRef"
        :data="menuTreeData"
        show-checkbox
        node-key="id"
        default-expand-all
        highlight-current
        :check-strictly="true"
        :render-after-expand="false"
        :props="{ label: 'name', children: 'children' }"
        @check-change="handleNodeClick"
      />
    </div>
  </div>
</template>

<script lang="ts" setup>
import { Role } from "@/api/interface";
import { getMenuTreeList } from "@/api/modules/menu";
import { useComponentRef } from "@/hooks/useComponentRef";
import { ElTree } from "element-plus";

defineOptions({
  name: "MenuPermission"
});

const props = defineProps<{
  role: Role.IRole;
}>();

const isIndeterminate = ref(false);
const menuTreeData = ref([]);
const checkAll = ref(false);
const treeRef = useComponentRef(ElTree);

const setMenuCheck = () => {
  const ids = extractIds(menuTreeData.value);
  treeRef.value?.setCheckedKeys(checkAll.value ? ids : []);
  isIndeterminate.value = false;
};

const setMenuOpenOrClose = expend => {
  const ids = extractIds(menuTreeData.value);
  ids.forEach((id: any) => {
    if (treeRef.value?.store.nodesMap[id]) {
      treeRef.value.store.nodesMap[id].expanded = expend;
    }
  });
};

const handleNodeClick = () => {
  const ids = extractIds(menuTreeData.value);
  const checkMenuLen = (treeRef.value?.getCheckedKeys() as number[]).length || 0;
  isIndeterminate.value = checkMenuLen > 0 && checkMenuLen < ids.length;
  checkAll.value = checkMenuLen === ids.length;
};

const getAllMenu = async () => {
  // 获取所有菜单
  const { data } = await getMenuTreeList();
  menuTreeData.value = data;
  // 判断当前菜单是否已经全选
  const ids = extractIds(data);
  const roleMenuLen = props.role.menus?.length || 0;
  checkAll.value = roleMenuLen === ids.length;

  if (props.role.menus) {
    isIndeterminate.value = roleMenuLen > 0 && roleMenuLen < ids.length;
    // 设置选中的菜单
    await nextTick();
    props.role.menus.forEach((id: any) => {
      treeRef.value?.setChecked(id, true, false);
    });
  }
};

const extractIds = (data: any[]): number[] => {
  const ids: number[] = [];
  data.forEach((item: any) => {
    ids.push(item.id);
    if (item.children && item.children.length > 0) {
      ids.push(...extractIds(item.children));
    }
  });
  return ids;
};

const getCheckedKeys = () => {
  const checkedNodes = treeRef.value?.getCheckedNodes(false, true);
  return checkedNodes ? checkedNodes.map((item: any) => item.id) : [];
};

watch(
  () => props.role,
  val => {
    if (!val.id) return;
    getAllMenu();
  },
  { immediate: true }
);

defineExpose({
  getCheckedKeys
});
</script>

<style lang="scss" scoped>
:deep(.el-checkbox__label) {
  font-size: 16px;
}
</style>
